package com.sparrow.common.hotswap2;

import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class HotSwapObjectManager {
    private static Logger logger = LoggerFactory.getLogger(HotSwapObjectManager.class);

    private final Map<String, Object> moduleInstances = new ConcurrentHashMap<>();
    private final Map<String, HotSwapClassLoader> classLoaders = new ConcurrentHashMap<>();
    private final Map<String, Integer> moduleVersions = new ConcurrentHashMap<>();
    private final Map<String, String> moduleMainClasses = new ConcurrentHashMap<>();
    private final CommonClassLoader commonClassLoader;

    public HotSwapObjectManager() {
        this.commonClassLoader = new CommonClassLoader();
        initializeModuleConfigs();
    }

    /**
     * 获取父类加载器 - 实现公共接口和基类的共享
     */
    private ClassLoader getParentClassLoader() {
        return commonClassLoader;
    }

    /**
     * 公共类加载器 - 加载接口和基类
     */
    private static class CommonClassLoader extends ClassLoader {
        private final Set<String> commonPackages = Sets.newHashSet(
                "com.game.common",
                "com.game.api",
                "com.game.interfaces",
                "java.",
                "javax.",
                "org.slf4j",
                "ch.qos.logback"
        );

        @Override
        protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
            // 公共包委托给父加载器（系统类加载器）
            for (String pkg : commonPackages) {
                if (name.startsWith(pkg)) {
                    return super.loadClass(name, resolve);
                }
            }

            // 其他类尝试自己加载（模块特定类）
            synchronized (getClassLoadingLock(name)) {
                // 首先检查是否已经加载
                Class<?> clazz = findLoadedClass(name);
                if (clazz != null) {
                    if (resolve) {
                        resolveClass(clazz);
                    }
                    return clazz;
                }

                // 对于非公共包，也委托给父加载器
                return super.loadClass(name, resolve);
            }
        }
    }

    /**
     * 获取模块主类名 - 根据模块名映射到具体的主类
     */
    private String getModuleMainClass(String moduleName) {
        String mainClass = moduleMainClasses.get(moduleName);
        if (mainClass == null) {
            throw new IllegalArgumentException("Unknown module: " + moduleName);
        }
        return mainClass;
    }

    /**
     * 初始化模块配置
     */
    private void initializeModuleConfigs() {
        // 可以从配置文件、数据库或注解中读取
        moduleMainClasses.put("player", "com.game.module.player.PlayerManager");
        moduleMainClasses.put("battle", "com.game.module.battle.BattleManager");
        moduleMainClasses.put("skill", "com.game.module.skill.SkillManager");
        moduleMainClasses.put("item", "com.game.module.item.ItemManager");
        moduleMainClasses.put("chat", "com.game.module.chat.ChatManager");
        moduleMainClasses.put("guild", "com.game.module.guild.GuildManager");
    }

    /**
     * 动态注册模块
     */
    public void registerModuleConfig(String moduleName, String mainClassName) {
        moduleMainClasses.put(moduleName, mainClassName);
    }



    /**
     * 热更模块 - 完整实现
     */
    public boolean hotSwapModule(String moduleName, File newClassPath,
                                 DataMigrator migrator) {
        if (!moduleMainClasses.containsKey(moduleName)) {
            logger.error("Module not registered: {}", moduleName);
            return false;
        }

        try {
            // 1. 创建安全点
//            createSafepoint(moduleName);

            // 2. 备份当前状态
            Object oldInstance = moduleInstances.get(moduleName);
            HotSwapClassLoader oldClassLoader = classLoaders.get(moduleName);
            int oldVersion = moduleVersions.getOrDefault(moduleName, 0);

            // 3. 验证新类文件
            if (!validateClassFiles(moduleName, newClassPath)) {
                logger.error("Class files validation failed for module: {}", moduleName);
                return false;
            }

            // 4. 创建新的类加载器
            int newVersion = oldVersion + 1;
            HotSwapClassLoader newClassLoader = new HotSwapClassLoader(
                    moduleName, newClassPath, newVersion, getParentClassLoader());

            // 5. 加载新类并创建实例
            String mainClassName = getModuleMainClass(moduleName);
            logger.info("Loading main class: {} for module: {}", mainClassName, moduleName);

            Class<?> newClass = newClassLoader.loadClass(mainClassName);
            Object newInstance = newClass.getDeclaredConstructor().newInstance();

            // 6. 初始化新实例
            initializeModuleInstance(newInstance, moduleName);

            // 7. 数据迁移
            if (migrator != null && oldInstance != null) {
                logger.info("Migrating data for module: {}", moduleName);
                migrator.migrateData(oldInstance, newInstance);
            } else if (oldInstance == null) {
                logger.info("No old instance found, skipping migration for module: {}", moduleName);
            }

            // 8. 原子切换
            synchronized (moduleInstances) {
                moduleInstances.put(moduleName, newInstance);
                classLoaders.put(moduleName, newClassLoader);
                moduleVersions.put(moduleName, newVersion);
            }

            logger.info("Hot swap successful for module: {} version: {} -> {}",
                    moduleName, oldVersion, newVersion);

            // 9. 清理旧版本
            if (oldClassLoader != null) {
                cleanupOldVersion(moduleName, oldClassLoader);
            }

//            // 10. 保存版本历史
//            VersionManager.getInstance().saveVersion(moduleName, newClassLoader,
//                    newInstance, newVersion);

            return true;

        } catch (Exception e) {
            logger.error("Hot swap failed for module: " + moduleName, e);
            // 自动回滚到旧版本
//            if (oldInstance != null && oldClassLoader != null) {
//                rollbackToVersion(moduleName, oldVersion, oldInstance, oldClassLoader);
//            }
            return false;
        } finally {
            // 11. 释放安全点
//            releaseSafepoint(moduleName);
        }
    }

    /**
     * 验证类文件完整性
     */
    private boolean validateClassFiles(String moduleName, File classPath) {
        String mainClassName = getModuleMainClass(moduleName);
        String classFile = mainClassName.replace('.', '/') + ".class";
        File mainClassFile = new File(classPath, classFile);

        if (!mainClassFile.exists()) {
            logger.error("Main class file not found: {}", mainClassFile.getAbsolutePath());
            return false;
        }

        // 检查类文件是否可读
        try {
            byte[] bytes = Files.readAllBytes(mainClassFile.toPath());
            if (bytes.length == 0) {
                logger.error("Main class file is empty: {}", mainClassFile.getAbsolutePath());
                return false;
            }
        } catch (IOException e) {
            logger.error("Failed to read main class file: {}", mainClassFile.getAbsolutePath(), e);
            return false;
        }

        return true;
    }

    /**
     * 初始化模块实例
     */
    private void initializeModuleInstance(Object instance, String moduleName) {
        try {
            // 调用初始化方法（如果存在）
            Method initMethod = instance.getClass().getMethod("initialize", String.class);
            initMethod.invoke(instance, moduleName);
            logger.info("Module initialized: {}", moduleName);
        } catch (NoSuchMethodException e) {
            // 没有initialize方法，跳过
            logger.debug("No initialize method found for module: {}", moduleName);
        } catch (Exception e) {
            logger.warn("Module initialization failed for: {}", moduleName, e);
        }
    }

    /**
     * 回滚到指定版本
     */
    private void rollbackToVersion(String moduleName, int version,
                                   Object instance, HotSwapClassLoader classLoader) {
        synchronized (moduleInstances) {
            moduleInstances.put(moduleName, instance);
            classLoaders.put(moduleName, classLoader);
            moduleVersions.put(moduleName, version);
        }
        logger.warn("Rolled back module: {} to version: {}", moduleName, version);
    }

    /**
     * 清理旧版本
     */
    private void cleanupOldVersion(String moduleName, HotSwapClassLoader oldClassLoader) {
        try {
            // 触发GC清理旧类加载器
            oldClassLoader.clearCache();
            logger.info("Cleaned up old class loader for module: {}", moduleName);
        } catch (Exception e) {
            logger.warn("Failed to cleanup old class loader for module: {}", moduleName, e);
        }
    }

}
